/*
 * sched.h - Estructures i macros pel tractament de processos
 */

#include <list.h>
#include <mm_address.h>
#include <stats.h>
#include <libc.h>
#include <mm.h>
#include <utils.h>

#ifndef __SCHED_H__
#define __SCHED_H__

#define NR_TASKS 10
#define KERNEL_STACK_SIZE	1024
#define DEFAULT_QUANTUM 64
#define FREE 0
#define READY 1
#define BLOCKED 2
#define NR_SEM 20
#define NR_CHANNELS 10

struct semaphore {
  int initialized;
  int value;
  unsigned int owner_pid;
  struct list_head blocked_list;
};

struct channel {
  struct open_file *open_file;
  int initialized;
};

struct keyboard_params {
  unsigned int remaining_bytes;
  unsigned int read_bytes;
  char *data_buffer;
};

struct task_struct {
  unsigned int pid;
  unsigned int ppid;
  unsigned int quantum;
  unsigned int stat; // Default is FREE
  struct list_head list;
  struct stats task_stats;
  int data_pages[NUM_PAG_DATA];
  struct channel channels[NR_CHANNELS];
  struct keyboard_params kb_params;
};

union task_union {
  struct task_struct task;
  unsigned long stack[KERNEL_STACK_SIZE];    /* pila de sistema, per procés */
};

struct protected_task_struct {
  unsigned long task_protect[KERNEL_STACK_SIZE];/* This field protects the different task_structs, so any acces to this field will generate a PAGE FAULT exeption */
  union task_union t;
};

extern struct protected_task_struct task[NR_TASKS];

extern struct semaphore sem[NR_SEM];

#define KERNEL_ESP       (DWord) &task[0].t.stack[KERNEL_STACK_SIZE]

extern unsigned int remaining_quantum;
extern unsigned int pending_eoi;
extern struct list_head runqueue;
extern struct list_head freequeue;
extern struct list_head keyboardqueue;
unsigned int next_pid;
unsigned int get_next_pid(void);

/* Initialize semaphores (mark as unused) */
void init_sems(void);

/* Initialize distinct task_struct info for a new process (set pid, init stats, etc.) */
void init_task_info(struct task_struct* t, unsigned int pid, unsigned int ppid);

/* Allocate new pages for user data and save their address in the task struct */
/* Returns 1 on success, returns 0 and does nothing when an error occurs */
int alloc_task_pages(struct task_struct* t);

/* Initialize task_structs, frequeue and runqueue */
void init_tasks(void);

/* Inicialitza les dades del proces inicial */
void init_task0(void);

/* Troba el primer canal lliure, li assigna el file descriptor i retorna el numero de canal */
int assign_channel(struct open_file *open_file);

/* Retorna el task struct actual */
struct task_struct* current();

/* Retorna el task struct corresponent a l'element de llista de processos passat com a argument */
struct task_struct* list_head_to_task_struct(struct list_head* l);

/* Retorna el punter al task_struct amb el pid que li passem per paràmetre si és actiu, altrament retorna 0 */
struct task_struct* get_active_task(unsigned int pid);

/* Efectua el canvi de context */
void task_switch(union task_union *t);

/* S'encarrega del schedule dels processos */
void scheduling();


void block_process(struct task_struct *ts, struct list_head *list);
void unblock_process(struct task_struct *ts, int return_value);

#endif  /* __SCHED_H__ */
